const WebSocket = require('ws');
const fs = require('fs');
const { exec } = require('child_process');
const path = require('path');

const wss = new WebSocket.Server({ port: 8082 });
const clientBuffers = new Map(); // 存储 { buffer: Buffer[], isEnd: boolean }

// 生成唯一客户端 ID
const generateClientId = () => {
    return `client-${Date.now()}-${Math.floor(Math.random() * 1000)}`;
};

// 计算缓冲区总长度
const sumBufferLength = (clientId) => {
    return clientBuffers.get(clientId).buffer.reduce((acc, chunk) => acc + chunk.length, 0);
};

// FFmpeg 转码（WAV → MP3）
const convertToMp3 = (wavPath, mp3Path, callback) => {
    const ffmpegCmd = `ffmpeg -i "${wavPath}" -vn -ab 128k -ar 44100 -y "${mp3Path}"`;
    exec(ffmpegCmd, (error, stdout, stderr) => {
        if (error) {
            callback(`转码失败: ${error.message}`);
            return;
        }
        callback(null, mp3Path);
    });
};

wss.on('connection', (ws) => {
    const clientId = generateClientId();
    clientBuffers.set(clientId, { buffer: [], isEnd: false });
    console.log(`新客户端连接: ${clientId}`);

    ws.on('message', (data) => {
        let controlMsg = null;
        const isJson = data.toString().startsWith('{') && data.toString().endsWith('}'); // 快速判断是否可能是 JSON

        try {
            if (isJson) {
                controlMsg = JSON.parse(data.toString());
            }
        } catch (error) {
            // 故意空着，让 controlMsg 保持 null
        }

        if (controlMsg !== null) {
            // 处理控制消息
            console.log(`[${clientId}] 收到控制消息:`, controlMsg);
            if (controlMsg.is_speaking === false) {
                clientBuffers.get(clientId).isEnd = true;
                processAudio(clientId);
            }
        } else {
            // 处理音频数据（支持 Buffer/ArrayBuffer/Blob）
            let bufferData;
            if (data instanceof Buffer) {
                bufferData = data;
            } else if (data instanceof Uint8Array) {
                bufferData = Buffer.from(data);
            } else if (data instanceof ArrayBuffer) {
                bufferData = Buffer.from(data);
            } else {
                console.warn(`[${clientId}] 不支持的数据类型:`, typeof data);
                return;
            }

            clientBuffers.get(clientId).buffer.push(bufferData);
            console.log(`[${clientId}] 收到音频数据块，当前总长度: ${sumBufferLength(clientId)}`);
        }
    });

    ws.on('close', () => {
        console.log(`[${clientId}] 连接关闭，处理剩余数据`);
        processAudio(clientId); // 连接关闭时处理残留数据
    });

    ws.on('error', (error) => {
        console.error(`[${clientId}] 连接错误:`, error);
        processAudio(clientId); // 错误时强制处理
    });
});

// 处理音频数据的核心函数
const processAudio = (clientId) => {
    const clientData = clientBuffers.get(clientId);
    if (!clientData || clientData.buffer.length === 0 && !clientData.isEnd) {
        clientBuffers.delete(clientId);
        return;
    }

    const audioBuffer = Buffer.concat(clientData.buffer);
    clientBuffers.delete(clientId);

    if (audioBuffer.length === 0) {
        console.log(`[${clientId}] 无有效音频数据`);
        return;
    }

    // 保存临时 WAV 文件（补充 WAV 头）
    const wavBuffer = addWavHeader(audioBuffer);
    const tempWavPath = path.join(__dirname, 'temp', `${clientId}.wav`);
    const outputMp3Path = path.join(__dirname, 'output', `${clientId}.mp3`);

    fs.writeFile(tempWavPath, wavBuffer, (err) => {
        if (err) {
            console.error(`[${clientId}] 写入临时文件失败:`, err);
            return;
        }

        convertToMp3(tempWavPath, outputMp3Path, (error, mp3Path) => {
            if (error) {
                console.error(`[${clientId}] ${error}`);
            } else {
                console.log(`[${clientId}] MP3 保存成功: ${mp3Path}`);
            }
            // fs.unlink(tempWavPath, () => {}); // 清理临时文件
        });
    });
};

// 补充 WAV 头（与 A 项目采样率一致：16000Hz, 16bit, 单声道）
const addWavHeader = (pcmBuffer) => {
    const sampleRate = 16000; // A 项目 Recorder 中设置的采样率
    const numChannels = 1; // 单声道
    const bitDepth = 16; // 16bit 采样

    // WAV 头总长度固定为 44 字节，后续是 PCM 数据
    const wavBuffer = Buffer.alloc(44 + pcmBuffer.length);

    // 写入 RIFF 头（4字节）
    wavBuffer.write('RIFF', 0);
    wavBuffer.writeUInt32LE(36 + pcmBuffer.length, 4); // 文件总大小（RIFF 头 + WAV 头 + PCM 数据）
    wavBuffer.write('WAVE', 8);

    // 写入 fmt 子块（24字节）
    wavBuffer.write('fmt ', 12);
    wavBuffer.writeUInt32LE(16, 16); // fmt 子块大小（固定为 16）
    wavBuffer.writeUInt16LE(1, 20); // 音频格式（PCM = 1）
    wavBuffer.writeUInt16LE(numChannels, 22); // 声道数
    wavBuffer.writeUInt32LE(sampleRate, 24); // 采样率
    wavBuffer.writeUInt32LE((sampleRate * numChannels * bitDepth) / 8, 28); // 字节率（采样率×声道数×位深/8）
    wavBuffer.writeUInt16LE((numChannels * bitDepth) / 8, 32); // 块对齐（声道数×位深/8）
    wavBuffer.writeUInt16LE(bitDepth, 34); // 位深

    // 写入 data 子块（8字节 + PCM 数据）
    wavBuffer.write('data', 36);
    wavBuffer.writeUInt32LE(pcmBuffer.length, 40); // PCM 数据大小

    // 写入 PCM 数据（关键修复：逐个字节复制）
    pcmBuffer.copy(wavBuffer, 44); // 将 PCM 数据复制到 WAV 缓冲区的 44 字节之后

    return wavBuffer;
};

// 初始化临时目录
fs.mkdirSync(path.join(__dirname, 'temp'), { recursive: true });
fs.mkdirSync(path.join(__dirname, 'output'), { recursive: true });
console.log('C项目启动，端口: 8082');